package Design;//给定一个 m x n 二维字符网格 board 和一个单词（字符串）列表 words，找出所有同时在二维网格和字典中出现的单词。
//
// 单词必须按照字母顺序，通过 相邻的单元格 内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使
//用。 
//
// 
//
// 示例 1： 
//
// 
//输入：board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f",
//"l","v"]], words = ["oath","pea","eat","rain"]
//输出：["eat","oath"]
// 
//
// 示例 2： 
//
// 
//输入：board = [["a","b"],["c","d"]], words = ["abcb"]
//输出：[]
// 
//
// 
//
// 提示： 
//
// 
// m == board.length 
// n == board[i].length 
// 1 <= m, n <= 12 
// board[i][j] 是一个小写英文字母 
// 1 <= words.length <= 3 * 10⁴ 
// 1 <= words[i].length <= 10 
// words[i] 由小写英文字母组成 
// words 中的所有字符串互不相同 
// 
// Related Topics 字典树 数组 字符串 回溯 矩阵 👍 564 👎 0


import java.util.*;

//leetcode submit region begin(Prohibit modification and deletion)
class findWords {

    int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    public List<String> findWords(char[][] board, String[] words) {
        Trie root = new Trie();
        //将所有字符串加入前缀树
        for(String word : words){
            root.insert(word);
        }
        int rows = board.length;
        int cols = board[0].length;

        Set<String> ans = new HashSet<>();
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                //遍历每一个格子的值作为起始位置，进行前缀树的回溯
                dfs(i,j,board,ans,root);
            }
        }

        return new ArrayList<String>(ans);

    }

    private void dfs(int i, int j, char[][] board, Set<String> ans, Trie root){
        //如果当前字符不在前缀树中,直接返回
        if(board[i][j]=='#' || root.getChildren()[board[i][j]-'a']==null){
            return ;
        }
        char cur = board[i][j];
        Trie node = root.getChildren()[cur-'a']; //拿到当前字符的前缀树节点
        board[i][j] = '#'; //标记已经访问
        //如果当前节点是一个字符串
        if(node.getIsEnd()){
            ans.add(node.getWord());
        }
        for(int[] dir : dirs){
            int curi = i+dir[0], curj = j+dir[1];
            if(curi>=0 && curi<board.length && curj>=0 && curj<board[0].length){
                dfs(curi, curj, board, ans, node);
            }
        }

        board[i][j] = cur; //还原字符

    }
}
//leetcode submit region end(Prohibit modification and deletion)
